package com.shujia.day09;

public class Demo04Generics {
    public static void main(String[] args) {
        /*
            TODO 泛型
                1.为什么需要泛型？
                   1.  对于有时调用某个类中的方法时，方法的参数类型需要明确，但是为了方法的使用广泛，
                        那么该方法的参数类型不能写死 而Java是一种强类型语言，必须要表示其类型是什么
                            所以需要使用某种 标记 来表示其类型
                   2. 对于集合在添加数据时，如果对数据不进行限制，那么对于其具体的元素只能泛化为Object的子类
                            实际使用时需要对其元素的类型进行明确,一般情况下,一个容器中,保存的数据应该为同一种类型
                   总结:泛型可以对类型进行控制
                2.泛型的书写格式
                   使用 <> 进行表示 并可以对 类进行修饰传参 / 方法进行修饰 / 变量

                泛型 可以表述一种未知的类型,可以增加方法的灵活性

         */
//        ArrayList arrayList = new ArrayList();
//        arrayList.add(1);
//        arrayList.add("字符串");
//
//        for (Object o : arrayList) {
//            System.out.println(o);
//        }

        /*
            TODO 当在类名旁使用<类型>进行表述时,就限定其 T = 类型
         */
        A<String> stringA = new A<>("张三");
        A<Name> nameA = new A<>(new Name("李", "亮"));
        nameA.name.printInfo();


        new B().fun("这是B类中的泛型方法");
        String string = new B().fun1("String");
        Integer integer = 1;
//        new B().<String>fun(integer);
        new B().<String>fun("integer");

        B b = new B();
        b.fun2(new Cat());

    }
}

class A<T> {
    T name;

    /*
        TODO A类的有参构造使用了 T 作为其参数类型
             T同时也是当前 A类中的一个属性
     */
    public A(T t) {
        this.name = t;
    }
}

class B {
    // TODO  public <E> 用于限制方法在调用时,对其中的参数进行限制类型
    public <E> void fun(E e) {
        System.out.println(e);
    }

    public <F> F fun1(F f) {
        return f;
    }

    // TODO 对于T泛型要求为一个动物
    public <T extends Animal> void fun2(T t) {
        t.eat();
        t.run();
    }



}

abstract class Animal {
    public abstract void run();

    public abstract void eat();
}

class Cat extends Animal {

    @Override
    public void run() {
        System.out.println("猫可以走猫步...");
    }

    @Override
    public void eat() {
        System.out.println("🐱爱吃鱼...");
    }
}

class JJLCat extends Cat{
    final String type = "金吉拉";
    String name;

    public JJLCat(String name) {
        this.name = name;
    }
}


class Name {
    String xing;
    String ming;

    public Name(String xing, String ming) {
        this.xing = xing;
        this.ming = ming;
    }

    public void printInfo() {
        System.out.println("在下免贵姓" + xing + "名" + ming);

    }
}

